#include "EditorLayer.h"

#include "Core/GlobalContext.h"

#include "Events/MouseEvent.h"
#include "Events/WindowEvent.h"

namespace SE
{
	void CameraController::onUpdate(Entity entity, const Double deltaMilliseconds)
	{
		SE_PROFILE_FUNCTION();

		if (!entity)
			return;

		auto& cameraComponent = entity.getComponent<CameraComponent>();
		auto& transformComponent = entity.getComponent<TransformComponent>();

		auto& cameraPosition = transformComponent.position;
		auto& rotation = transformComponent.rotation;

		Float ts = Float(deltaMilliseconds / 1000.0f);

		auto positionOffset = Vector3f(0.0f);
		if (WindowAPI::IsKeyboardButtonPressed(KeyboardButton::KEYB_A))
		{
			Vector3f direction = glm::normalize(glm::toMat3(Quaternion(rotation)) * -CameraWorldRight);
			if (MoveMode::FollowForward == mMoveMode)
			{
				positionOffset += direction * mCameraMoveSpeed * ts;
			}
		}
		if (WindowAPI::IsKeyboardButtonPressed(KeyboardButton::KEYB_D))
		{
			Vector3f direction = glm::normalize(glm::toMat3(Quaternion(rotation)) * CameraWorldRight);
			if (MoveMode::FollowForward == mMoveMode)
			{
				positionOffset += direction * mCameraMoveSpeed * ts;
			}
		}
		if (WindowAPI::IsKeyboardButtonPressed(KeyboardButton::KEYB_W))
		{
			Vector3f direction = glm::normalize(glm::toMat3(Quaternion(rotation)) * CameraWorldForward);
			if (MoveMode::FollowForward == mMoveMode)
			{
				positionOffset += direction * mCameraMoveSpeed * ts;
			}
		}
		if (WindowAPI::IsKeyboardButtonPressed(KeyboardButton::KEYB_S))
		{
			Vector3f direction = glm::normalize(glm::toMat3(Quaternion(rotation)) * -CameraWorldForward);
			if (MoveMode::FollowForward == mMoveMode)
			{
				positionOffset += direction * mCameraMoveSpeed * ts;
			}
		}
		if (WindowAPI::IsKeyboardButtonPressed(KeyboardButton::KEYB_SPACE))
		{
			Vector3f direction = glm::normalize(glm::toMat3(Quaternion(rotation)) * CameraWorldUp);
			if (MoveMode::FollowForward == mMoveMode)
			{
				positionOffset += direction * mCameraMoveSpeed * ts;
			}
		}
		if (WindowAPI::IsKeyboardButtonPressed(KeyboardButton::KEYB_LEFT_SHIFT))
		{
			Vector3f direction = glm::normalize(glm::toMat3(Quaternion(rotation)) * -CameraWorldUp);
			if (MoveMode::FollowForward == mMoveMode)
			{
				positionOffset += direction * mCameraMoveSpeed * ts;
			}
		}
		cameraPosition += positionOffset;


		if (WindowAPI::IsKeyboardButtonPressed(KeyboardButton::KEYB_LEFT_ALT))
		{
			mIsMouseFocused = (mIsMouseFocused + 1) % 2;
			WindowAPI::SetCursorFocused(mIsMouseFocused);
			mIsMouseFirstInScreen = true;
		}

		if (mIsMouseFocused)
		{
			auto currentPosition = WindowAPI::GetMousePosition();
			if (mIsMouseFirstInScreen)
			{
				mLastMousePosition = currentPosition;
				mIsMouseFirstInScreen = false;
			}

			auto offset = currentPosition - mLastMousePosition;

			if (!Math::realEqual(offset.x, mLastMousePosition.x) || !Math::realEqual(offset.y, mLastMousePosition.y))
			{
				rotation.x -= offset.y * mPanMoveSpeed / 1000.0f;
				rotation.y -= offset.x * mPanMoveSpeed / 1000.0f;
				mLastMousePosition = currentPosition;
			}
		}
	}

	EditorLayer::EditorLayer()
	{
		mScene = CreateRef<Scene>();

		// Use default camera configurations.
		auto cameraEntity = mScene->createEntity("Scene camera");
		cameraEntity.getComponent<TransformComponent>().position.z = 10.0f;
		cameraEntity.addComponent<ScriptableComponent>().bind<CameraController>();
		auto& cameraComponent = cameraEntity.addComponent<CameraComponent>();
		cameraComponent.actived = true;

		auto assetPath = GlobalContext::GetConfigManager()->getAssetsDir();

		mSceneHierarchyPanel = CreateRef<SceneHierarchyPanel>();
		mSceneHierarchyPanel->setCurrentScene(mScene);
	}

	EditorLayer::~EditorLayer()
	{
	}

	void EditorLayer::onCompute(const Double deltaMilliseconds)
	{
		mScene->onCompute(deltaMilliseconds);
	}

	void EditorLayer::onRender(const Double deltaMilliseconds)
	{
		ImGui::DockSpaceOverViewport(ImGui::GetMainViewport());

		mScene->onRender(deltaMilliseconds);
		mSceneHierarchyPanel->onRender(deltaMilliseconds);
	}

	String EditorLayer::getName() const
	{
		return "Editor Layer";
	}
} // !namespace SE